package com.itheima.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.itheima.constant.MessageConstant;
import com.itheima.entity.Result;
import com.itheima.service.MemberService;
import com.itheima.service.ReportService;
import com.itheima.service.SetmealService;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.Test;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 会员图表操作
 */
@RestController
@RequestMapping("/report")
public class ReportController {
    @Reference
    public MemberService memberService;
    @Reference
    public SetmealService setmealService;

    /**
     * 会员数量统计
     * map集合封装数据，javabean对象 {} ， 数据或者集合 []
     *
     * @return
     */
    @RequestMapping("/getMemberReport")
    public Result getMemberReport() {
        Map<String, Object> map = new HashMap<>();
        Calendar calendar = Calendar.getInstance();
        //获取当前日期之前12月的日期
        calendar.add(Calendar.MONTH, -12);
        List<String> list = new ArrayList<>();
        for (int i = 0; i <= 12; i++) {
            calendar.add(Calendar.MONTH, 1);
           /*
                获取当前月份之前的12个月份，calendar.getTime()获取当前时间
                format：将日期转换为指定的字符串
                parse ：将指定的日期字符串转换为日期对象date
           */
            list.add(new SimpleDateFormat("yyyy-MM").format(calendar.getTime()));
        }
        map.put("months", list);
        //根据月份查询每个月的会员数量
        List<Integer> memberCountByMonths = memberService.getMemberCountByMonths(list);
        map.put("memberCount", memberCountByMonths);
        return new Result(true, MessageConstant.GET_MEMBER_NUMBER_REPORT_SUCCESS, map);
    }

    /**
     * 套餐预约占比,java对象转换为json对象{},数组和集合转换为json对象为[]
     * 一个map集合封装这扇形图所需的数据 一个list集合，另一个list集合中存有map集合（套餐及具体预约人数）
     * {"data":{
     * "setmealNames":["入职无忧体检套餐（男女通用）","珍爱高端升级肿瘤12项筛查（男女单人）",
     * "粉红珍爱(女)升级TM12项筛查体检套餐","阳光爸妈升级肿瘤12项筛查（男女单人）体检套餐"],
     * "setmealCount":[
     * {"name":"入职无忧体检套餐（男女通用）","value":2},
     * {"name":"珍爱高端升级肿瘤12项筛查（男女单人）","value":1},
     * {"name":"粉红珍爱(女)升级TM12项筛查体检套餐","value":2},
     * {"name":"阳光爸妈升级肿瘤12项筛查（男女单人）体检套餐","value":1}
     * ]},
     * "flag":true,
     * "message":"获取套餐统计数据成功"
     * }
     *
     * @return
     */
    @RequestMapping("/getSetmealReport")
    public Result getSetmealReport() {
        //查询及数据库所有套餐的名称和已预约的数量
        Map<String, Object> data = new HashMap<>();
        try {
            List<Map<String, Object>> setmealCount = setmealService.findSetmealCount();

            //遍历list集合取出每一个map，从而获取map集合中的name属性
            List<String> setmealList = new ArrayList<>();
            for (Map<String, Object> map : setmealCount) {
                //套餐名称
                String name = (String) map.get("name");
                setmealList.add(name);
            }
            // echart扇形图展示所需数据
            data.put("setmealNames", setmealList);
            data.put("setmealCount", setmealCount);
            return new Result(true, MessageConstant.GET_SETMEAL_COUNT_REPORT_SUCCESS, data);
        } catch (Exception e) {
            return new Result(false, MessageConstant.GET_SETMEAL_LIST_FAIL);
        }
    }

    /**
     * 运营数据统计
     * 没有对应的javabean对象去封装一个json数据时，考虑使用map集合取封装！
     * todayNewMember -> number
     * totalMember -> number
     * thisWeekNewMember -> number
     * thisMonthNewMember -> number
     * todayOrderNumber -> number
     * todayVisitsNumber -> number
     * thisWeekOrderNumber -> number
     * thisWeekVisitsNumber -> number
     * thisMonthOrderNumber -> number
     * thisMonthVisitsNumber -> number
     * hotSetmeals -> List<Setmeal>
     * 考虑到该表单需要众多数据，所以单独增加一个接口，用于提供对应的服务！
     */
    @Reference
    public ReportService reportService;//注入服务，用于获取表单的各类数据

    @RequestMapping("/getBusinessReportData")
    public Result getBusinessReportData() {
        Map<String, Object> map = null;
        try {
            map = reportService.getBusinessReportData();
            return new Result(true, MessageConstant.GET_BUSINESS_REPORT_SUCCESS, map);
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false, MessageConstant.GET_BUSINESS_REPORT_FAIL);
        }
    }

    /**
     * 导出运营数据统计表
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("/exportBusinessReport")
    public Result exportBusinessReport(HttpServletRequest request, HttpServletResponse response) throws Exception {
        try {
            //远程调用报表服务获取报表数据
            Map<String, Object> data = reportService.getBusinessReportData();

            //取出报表数据
            String reportDate = (String) data.get("reportDate");
            Integer todayNewMember = (Integer) data.get("todayNewMember");
            Integer totalMember = (Integer) data.get("totalMember");
            Integer thisWeekNewMember = (Integer) data.get("thisWeekNewMember");
            Integer thisMonthNewMember = (Integer) data.get("thisMonthNewMember");
            Integer todayOrderNumber = (Integer) data.get("todayOrderNumber");
            Integer thisWeekOrderNumber = (Integer) data.get("thisWeekOrderNumber");
            Integer thisMonthOrderNumber = (Integer) data.get("thisMonthOrderNumber");
            Integer todayVisitsNumber = (Integer) data.get("todayVisitsNumber");
            Integer thisWeekVisitsNumber = (Integer) data.get("thisWeekVisitsNumber");
            Integer thisMonthVisitsNumber = (Integer) data.get("thisMonthVisitsNumber");
            List<Map> hotSetmeal = (List<Map>) data.get("hotSetmeal");
            //excel模板文件的絕對路徑  File.separator 分隔符 使用該方法便於適應不同系統做出區分
            String templateRelPath = request.getSession().getServletContext().getRealPath("template") + File.separator + "report_template.xlsx";
            //读取模板文件创建Excel表格对象
            XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(new File(templateRelPath)));
            //获取第一个工作簿
            XSSFSheet sheet = workbook.getSheetAt(0);

            //补齐日期
            XSSFRow row = sheet.getRow(2);
            row.getCell(5).setCellValue(reportDate);

            row = sheet.getRow(4);
            row.getCell(5).setCellValue(todayNewMember);//新增会员数（本日）
            row.getCell(7).setCellValue(totalMember);//总会员数

            row = sheet.getRow(5);
            row.getCell(5).setCellValue(thisWeekNewMember);//本周新增会员数
            row.getCell(7).setCellValue(thisMonthNewMember);//本月新增会员数

            row = sheet.getRow(7);
            row.getCell(5).setCellValue(todayOrderNumber);//今日预约数
            row.getCell(7).setCellValue(todayVisitsNumber);//今日到诊数

            row = sheet.getRow(8);
            row.getCell(5).setCellValue(thisWeekOrderNumber);//本周预约数
            row.getCell(7).setCellValue(thisWeekVisitsNumber);//本周到诊数

            row = sheet.getRow(9);
            row.getCell(5).setCellValue(thisMonthOrderNumber);//本月预约数
            row.getCell(7).setCellValue(thisMonthVisitsNumber);//本月到诊数

            int rowNum = 12;
            for (Map map : hotSetmeal) {
                String name = (String) map.get("name");
                Long setmeal_count = (Long) map.get("setmeal_count");
                BigDecimal proportion = (BigDecimal) map.get("proportion");
                row = sheet.getRow(rowNum++);
                row.getCell(4).setCellValue(name);//套餐名称
                row.getCell(5).setCellValue(setmeal_count);//预约数量
                row.getCell(6).setCellValue(proportion.doubleValue());//占比
            }

            //通过输出流对文件进行下载
            ServletOutputStream outputStream = response.getOutputStream();
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("content-Disposition", "attachment;filename=report.xlsx");
            workbook.write(outputStream);

            outputStream.flush();
            outputStream.close();
            workbook.close();
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false, MessageConstant.GET_BUSINESS_REPORT_FAIL, null);
        }
    }

    /**
     * 导出PDF格式的商业运营数据
     *
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping("/exportBusinessReport4PDF")
    public Result exportBusinessReport4PDF(HttpServletRequest request, HttpServletResponse response) throws Exception {
        try {
            //远程调用报表服务获取报表数据
            Map<String, Object> data = reportService.getBusinessReportData();

            List<Map> hotSetmeal = (List<Map>) data.get("hotSetmeal");
            //PDF模板文件的絕對路徑  File.separator 分隔符 使用該方法便於適應不同系統做出區分
            String jrxmlPath = request.getSession().getServletContext().getRealPath("template") + File.separator + "health_business3.jrxml";
            String jasperPath = request.getSession().getServletContext().getRealPath("template") + File.separator + "health_business3.jasper";

            //编译模板文件
            JasperCompileManager.compileReportToFile(jrxmlPath, jasperPath);

            //填充数据，使用javabean方式填充
            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperPath, data, new JRBeanCollectionDataSource(hotSetmeal));

            //通过输出流对文件进行下载
            ServletOutputStream outputStream = response.getOutputStream();
            response.setContentType("application/pdf");
            response.setHeader("content-Disposition", "attachment;filename=report.pdf");
            //输出文件
            JasperExportManager.exportReportToPdfStream(jasperPrint, outputStream);
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false, MessageConstant.GET_BUSINESS_REPORT_FAIL, null);
        }
    }

    /**
     * 疫情数据统计分析-->页面加载时调用远程接口获取json数据，再讲json数据传入controller层进行筛选
     * {
     * "date": "2020-01-24",
     * "confirmedNum": 1297,
     * "suspectedNum": 1965,
     * "curesNum": 38,
     * "deathsNum": 41,
     * "suspectedIncr": 1118
     * }
     *
     * @param map
     * @return
     */
    @RequestMapping("/getSeckData")
    public Result getSeckData(@RequestBody List<Map> map) {

        try {
            //创建一个map用于存取疫情所需所有的数据
            Map<String, Object> seckMap = new HashMap<>();
            //用于存储至今所有的时间
            ArrayList<String> dates = new ArrayList<>();
            //用于存储累计至今的累计确诊人数
            ArrayList<Integer> confirmedNums = new ArrayList<>();
            //用于存储累计至今的累计疑似人数
            ArrayList<Integer> suspectedNums = new ArrayList<>();
            //用于存储累计至今的死亡人数
            ArrayList<Integer> deathNums = new ArrayList<>();
            //用于存储累计至今的治愈人数
            ArrayList<Integer> curesNums = new ArrayList<>();
            for (Map map1 : map) {
                //获取日期
                String date = (String) map1.get("date");
                //获取当日累计确诊人数
                Integer confirmedNum = (Integer) map1.get("confirmedNum");
                //获取当日累计疑似人数
                Integer suspectedNum = (Integer) map1.get("suspectedNum");
                //获取当日累计疑似人数
                Integer deathsNum = (Integer) map1.get("deathsNum");
                //获取当日累计疑似人数
                Integer curesNum = (Integer) map1.get("curesNum");

                //将数据保存至相应的集合中
                dates.add(date);
                confirmedNums.add(confirmedNum);
                suspectedNums.add(suspectedNum);
                deathNums.add(deathsNum);
                curesNums.add(curesNum);
            }

            //将数据进行反转
            Collections.reverse(dates);
            Collections.reverse(confirmedNums);
            Collections.reverse(suspectedNums);
            Collections.reverse(deathNums);
            Collections.reverse(curesNums);

            //将list集合封装进map集合
            seckMap.put("dates", dates);
            seckMap.put("confirmedNums", confirmedNums);
            seckMap.put("deathNums", deathNums);
            seckMap.put("suspectedNums", suspectedNums);
            seckMap.put("curesNums", curesNums);

            return new Result(true, "数据已查询！", seckMap);
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false, "数据查询异常");
        }
    }

    @Test
    public void test() {
        Calendar calendar = Calendar.getInstance();
        //获取当前日期之前12月的日期
        calendar.add(Calendar.MONTH, -12);
        List<String> list = new ArrayList<>();
        for (int i = 1; i <= 12; i++) {
            calendar.add(Calendar.MONTH, 1);
           /*
                获取当前月份之前的12个月份，calendar.getTime()获取当前时间
                format：将日期转换为指定的字符串
                parse ：将指定的日期字符串转换为日期对象date
           */
            list.add(new SimpleDateFormat("yyyy-MM").format(calendar.getTime()));
        }
        System.out.println(list);
    }
}
